package com.eascs.admin.o2o.loanAccount.serviceimpl;

import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.eascs.account.api.IAccountService;
import com.eascs.account.api.IFeeService;
import com.eascs.account.api.constants.enums.AccountType;
import com.eascs.account.api.constants.enums.SourceType;
import com.eascs.account.api.constants.enums.TradeType;
import com.eascs.account.api.vo.CreateAccountParamVO;
import com.eascs.account.api.vo.TradeDetailVO;
import com.eascs.account.api.vo.TradeParamsVO;
import com.eascs.admin.common.utils.AccountConstants;
import com.eascs.admin.o2o.internal.dao.LoanapplyExpandDao;
import com.eascs.admin.o2o.internal.entity.LoanapplyExpand;
import com.eascs.admin.o2o.internal.service.LoanapplyExpandService;
import com.eascs.admin.o2o.internal.util.StatusContexts;
import com.eascs.admin.o2o.loan.entity.DFEmailContentVO;
import com.eascs.admin.o2o.loan.entity.O2oLoanapplyEntity;
import com.eascs.admin.o2o.loan.service.IO2oLoanapplyExpandRecordService;
import com.eascs.admin.o2o.loan.service.O2oLoanapplyService;
import com.eascs.admin.o2o.loanAccount.dao.AccountLogDao;
import com.eascs.admin.o2o.loanAccount.dao.O2oLoanapplyAccountDao;
import com.eascs.admin.o2o.loanAccount.entity.AccountLog;
import com.eascs.admin.o2o.loanAccount.entity.O2oLoanapplyAccountEntity;
import com.eascs.admin.o2o.loanAccount.service.IAccountLogService;
import com.eascs.app.dao.PageResult;
import com.eascs.app.dao.SqlPageQuery;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.common.util.StringUtil;
import com.eascs.common.util.UuidUtil;
import com.eascs.crm.common.custnew.entity.CustomerEntity;
import com.eascs.crm.common.custnew.service.CustomerService;
import com.eascs.notify.mail.MailNotifier;
import com.eascs.notify.mail.MailNotifyRequest;
import com.eascs.notify.mail.MailSendType;
import com.eascs.workflow.common.vo.ModelResult;

import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;

@Service
public class O2oLoanapplyAccountservice {
	
	
	@Autowired
	O2oLoanapplyAccountDao o2oLoanapplyAccountDao;
	@Reference
	IAccountService iAccountService;
	@Autowired
	O2oLoanapplyService o2oLoanapplyService;
	@Reference
	IAccountLogService iAccountLogService;
	
	@Reference
	private MailNotifier mailNotifier;
	
	@Autowired
	AccountLogDao accountLogDao;
	
	
	@Value("${msg.message.receivers}")
	private String receivers;	//短信接收者
	
	@Reference
	private IO2oLoanapplyExpandRecordService iO2oLoanapplyExpandRecordService;
	
	@Autowired
	private O2oLoanapplyAccountImpl io2oLoanapplyAccountService;
	
	@Reference
	private IFeeService iFeeService;
	
	@Reference
	private CustomerService customerService;
	
	@Autowired
	private LoanapplyExpandDao loanapplyExpandDao;
	
	@Autowired
	private LoanapplyExpandService loanapplyExpandService;
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());


	/**
	 * 贷款单划拨
	 */
	public void OpenLoanAccount(){
		String querySql = " select * from o2o_loanapply_account where status = '0' ";
		int pageIndex = 0;
		int pageSize = 100;
		CreateAccountParamVO vo = new CreateAccountParamVO();
		while (pageIndex >= 0) {
			logger.info("业务表o2o_loanapply_account表数据入库任务运行中，正在查询第[{}]页数据", pageIndex);
			SqlPageQuery<O2oLoanapplyAccountEntity> sqlPageQuery = new SqlPageQuery<>(O2oLoanapplyAccountEntity.class, pageSize,
					pageIndex, querySql);
			PageResult<O2oLoanapplyAccountEntity> results = o2oLoanapplyAccountDao.findDataWithPageForMysql(sqlPageQuery);

			List<O2oLoanapplyAccountEntity> list = results.getData();
			AccountLog accountLog = new AccountLog();
			String sentToEmailUrl = receivers;
			O2oLoanapplyEntity loan = null;
			MailNotifyRequest mailNotifyRequest = new MailNotifyRequest();
			mailNotifyRequest.setSystemCode("业务系统");
			mailNotifyRequest.setMailSendType(MailSendType.INSTANT);
			mailNotifyRequest.setTitle("贷款单账户失败通知");
			
			for (O2oLoanapplyAccountEntity account : list) {
				loan = o2oLoanapplyService.findById(account.getLoanapplyNo());
				grkh(account,accountLog,mailNotifyRequest,loan,vo,sentToEmailUrl);
			
			}
			
			if(results.getReturnDataSize() < pageSize ) break;
			
		}

	}
	
	@Transactional(transactionManager = "o2oTransactionManager")
	private void grkh(O2oLoanapplyAccountEntity account,AccountLog accountLog,
			MailNotifyRequest mailNotifyRequest,O2oLoanapplyEntity loan,
			CreateAccountParamVO vo,String sentToEmailUrl){
		
		DFEmailContentVO contentVo = new DFEmailContentVO();
		contentVo.setTitle("贷款单账户失败通知");
		contentVo.setBillCode(loan.getBillCode());
		contentVo.setDcTime(new Date());
		try {
			accountLog.setStartTime(new Date());
			accountLog.setId(UuidUtil.generateShortUuid());
			mailNotifyRequest.setRequestId(accountLog.getId());
			
			mailNotifyRequest.setBizCode(loan.getBillCode());
			mailNotifyRequest.setRecipientTo(sentToEmailUrl);
			mailNotifyRequest.setRequestDateTime(new Date());
			vo.setAccountType(AccountType.LOAN);
			vo.setBizId(loan.getLoanapplyNo());
			vo.setCustomerName(loan.getBillCode());
			vo.setRequestId(accountLog.getId());
			vo.setSource(SourceType.WEB);
			//vo.setSource(SourceType.WEB);
			ModelResult<String> result = null;
			result = iAccountService.createAccount(vo);
			if(result!=null && result.isSuccess()&&result.getModel()!=null){
				account.setAccountNo(result.getModel());
				account.setStatus(StatusContexts.O2O_ONE);
				logger.info("贷款单[{}]，开户成功",loan.getBillCode() );
			}else{
				logger.debug(result.getErrCode(), result.getErrMsg());
				logger.info("贷款单[{}]，开户失败原因。",result.getErrMsg() );
				// 生成邮件内容
				String content = convertEmailContent(contentVo);
				if (StringUtils.isNotBlank(content)) {
					mailNotifyRequest.setContent(content);
					mailNotifier.notify(mailNotifyRequest);
					logger.info("referCode:[{}],sentToEmailUrl,开始发送邮件入库成功", loan.getBillCode(), sentToEmailUrl);
				} else {
					logger.info("referCode:[{}],sentToEmailUrl:[{}],toList:[{}],生成邮件内容为空", loan.getBillCode(), sentToEmailUrl);
				}
			}
			accountLog.setStatus(String.valueOf(result.isSuccess()));
			accountLog.setEndTime(new Date());
			accountLog.setRequestid(account.getId());
			accountLog.setRequestPs(JSONObject.toJSONString(vo));
			accountLog.setResponsePs(JSONObject.toJSONString(result));
			accountLog.setClassname(this.getClass().getName());
			accountLog.setLogType(AccountConstants.LOAN_OPEN_ACCOUNT);
			accountLog.setLoanapplyNo(loan.getLoanapplyNo());
			// AccountConstants
			accountLog.setMethodname(Thread.currentThread().getStackTrace()[1].getMethodName());
			iAccountLogService.add(accountLog);
			o2oLoanapplyAccountDao.updateById(account);
		} catch (Exception e) {
			logger.debug(e.getMessage());
			// 生成邮件内容
			String content = convertEmailContent(contentVo);
			if (StringUtils.isNotBlank(content)) {
				contentVo.setTitle(e.getMessage());
				mailNotifyRequest.setContent(content);
				mailNotifier.notify(mailNotifyRequest);
				logger.info("referCode:[{}],sentToEmailUrl,开始发送邮件入库成功", loan.getBillCode(), sentToEmailUrl);
			} else {
				logger.info("referCode:[{}],sentToEmailUrl:[{}],toList:[{}],生成邮件内容为空", loan.getBillCode(), sentToEmailUrl);
			}
		}
	}
	
	private String convertEmailContent(DFEmailContentVO vo) {
		// 通过指定模板名获取FreeMarker模板实例
		try {
			Configuration configuration = new Configuration(Configuration.VERSION_2_3_24);
			configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/email/"));
			Template template = configuration.getTemplate("loanAccountEmailTemplate.ftl");
			StringWriter stringWriter = new StringWriter();
			// FreeMarker通过Map传递动态数据
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("email", vo);
			template.process(map, stringWriter);
			String htmlText = stringWriter.toString();
			return htmlText;
		} catch (Exception e) {
			logger.error("生成邮件模板失败", e);
		}
		return null;
	}
	
	/**
	 * 贷款单结清 保证金划扣到个人账户
	 */
	public void LoanAccountBZJHK(){
		String querySql = " select ola.id,ola.loanapply_no from o2o_loanapply ol LEFT JOIN  o2o_loanapply_account ola on ol.loanapply_no = ola.loanapply_no "
				+ " where ola.jqstatus = '0' and ol.wf_type ='HN' ";
		int pageIndex = 0;
		int pageSize = 50;
		CreateAccountParamVO vo = new CreateAccountParamVO();
		while (pageIndex >= 0) {
			logger.info("结清 划扣保证金 功能，正在查询第[{}]页数据", pageIndex);
			SqlPageQuery<Object[]> sqlPageQuery = new SqlPageQuery<>(Object[].class, pageSize, pageIndex);
			
			sqlPageQuery.setQuerySql(querySql.toString());
			
			PageResult<Object[]>  results = o2oLoanapplyAccountDao.findDataWithPage(sqlPageQuery);;
			List <Object[]> list = results.getData();
		
			//O2oLoanapplyEntity loan = null;
			MailNotifyRequest mailNotifyRequest = new MailNotifyRequest();
			mailNotifyRequest.setSystemCode("业务系统");
			mailNotifyRequest.setMailSendType(MailSendType.INSTANT);
			mailNotifyRequest.setTitle("结清划扣保证金失败通知");
			
			for (Object[] account : list) {
				LoanapplyExpand loanapplyExpand = loanapplyExpandService.queryLoanapplyNo(String.valueOf(account[1]));
				// O2oLoanapplyExpand expand = iO2oLoanapplyExpandRecordService.queryById(String.valueOf(account[0]));
				String result = "";
				try {
					result = ChargingJQ(loanapplyExpand);
				} catch (RuntimeException e) {
					result = e.getMessage();
					// TODO: handle exception
				}
				
				logger.info("结清 划扣保证金 ，返回数据[{}],Loanapply中id[{}]", result,String.valueOf(account[1]));
			
			}
			
			if(results.getReturnDataSize() < pageSize ) break;

		}

	}
	
	/**
	 * 结清 划扣保证金到
	 * 
	 * @param expand
	 * @param type
	 * @return
	 */
	@Transactional(transactionManager = "o2oTransactionManager")
	public String ChargingJQ(LoanapplyExpand expand) {

		if (null == expand) {
			return "未找到收费记录。";
		} 
		AccountLog accountLog = new AccountLog();
		accountLog.setStartTime(new Date());
		accountLog.setId(UuidUtil.generateShortUuid());

		String bizType = "";
		TradeType recDepositeTradeType = null;
		String remark = "";

		TradeParamsVO paramsVO = new TradeParamsVO();
		List<TradeDetailVO> detailsVO = new ArrayList<TradeDetailVO>();
		O2oLoanapplyAccountEntity loanapplyAccountEntity = io2oLoanapplyAccountService.getEntityByLoanapplyNo(expand.getLoanapply_no());
		if (null == loanapplyAccountEntity) {
			return "贷款单账户未开户，请联系运维同事";
		} else if (StringUtil.isBlank(loanapplyAccountEntity.getAccountNo())) {
			return "贷款单账户未开户，请稍后重试";
		}
		CustomerEntity getCustomerEntity = getCustomerEntity(expand.getLoanapply_no());
		if (null == getCustomerEntity) {
			return "借款人个人账户未开户，请联系运维同事";
		}
		
		if(!StatusContexts.WFTYPE_STATUS_CLO.equals(expand.getBillStatus())){
			return "借款人保证金管理费流程未结束";
		}
		
		if(!StatusContexts.WFTYPE_STATUS_CLO.equals(expand.getBillStatus())){
			
			return "借款人保证金管理费流程未结束";
		}
		
		if(expand.getRedDeposite()==null){
			
			return "借款人保证金管理费收费金额为空";
		}
		
		if(expand.getRetaDeposite()==null){  //已退保证金
			expand.setRetaDeposite(BigDecimal.ZERO);
		}
		
		
		if(expand.getRedDeposite().compareTo(expand.getRetaDeposite())<=0){
			expand.setRetaDeposite(BigDecimal.ZERO);
			return "保证金已收减已退小于等于0，无法结清";
		}
		
		TradeDetailVO recDeposite = new TradeDetailVO();// 封装保证金数据
		
		bizType = AccountConstants.ACCOUNT_QJ_BZJ;
		recDepositeTradeType = TradeType.DEPOSIT_OUT;
		remark = "划扣（退保证金到个人账户）";
		recDeposite.setAmount(expand.getRedDeposite().subtract(expand.getRetaDeposite()));  //金额取已收-已退
		recDeposite.setRollInAccount(getCustomerEntity.getAccountId());// 转出账户
		recDeposite.setRollOutAccount(loanapplyAccountEntity.getAccountNo());// 转入账户
		recDeposite.setTradeType(recDepositeTradeType);
		recDeposite.setTradeBankcardNoIn("");// 本方交易银行卡号
		recDeposite.setTradeBankcardNoOut("");// 对方交易银行卡号
		recDeposite.setTradeDate(new Date());
		recDeposite.setRemark("结清，划扣保证金，贷款单帐号："+expand.getBillCode());
		
		detailsVO.add(recDeposite);

		paramsVO.setBizId(expand.getId());
		paramsVO.setBizType(bizType);
		paramsVO.setDetails(detailsVO);
		paramsVO.setRemark(remark);
		paramsVO.setRequestId(accountLog.getId());
		paramsVO.setSource(SourceType.WEB);
		paramsVO.setUniqueId(expand.getId());
		ModelResult<String> result = null;
		try {
			logger.info("调用扣费接口开始，参数：【{}】", JSONObject.toJSONString(paramsVO));
			result = iFeeService.fee(paramsVO);
			accountLog.setStatus(String.valueOf(result.isSuccess()));
			accountLog.setEndTime(new Date());
			accountLog.setRequestid(expand.getId());
			accountLog.setRequestPs(JSONObject.toJSONString(paramsVO));
			accountLog.setResponsePs(JSONObject.toJSONString(result));
			accountLog.setClassname(this.getClass().getName());
			accountLog.setLogType(bizType);
			accountLog.setLoanapplyNo(expand.getLoanapply_no());
			accountLog.setMethodname(Thread.currentThread().getStackTrace()[1].getMethodName());
			
			logger.info("调用扣费接口结束，成功与否：{},【信息：{}】", result.isSuccess(), result.getErrMsg());
			if (result.isSuccess()) {// 如果调用成功
				
				logger.info("调用临时表接口开始，参数：【{}】", JSONObject.toJSONString(expand));
				
				expand.setRecDeposite(expand.getRedDeposite());
				int i = loanapplyExpandDao.updateById(expand);
				logger.info("loanapplyExpand，更新条数：【{}】",  i);
				
				loanapplyAccountEntity.setJqstatus(StatusContexts.O2O_ONE);
				int j = loanapplyExpandDao.updateById(loanapplyAccountEntity);
				logger.info("loanapplyAccountEntity，更新条数：【{}】",  j);
				
				return "SUCCESS";
			} else {
				return result.getErrMsg();
			}
		} catch (Exception e) {
			logger.error("调用退保证金（结清）接口失败，失败信息为：{}", e.getMessage());
			throw new RuntimeException("退保证金（结清）失败");
			//return "退保证金（结清）失败";
		}finally {
			logger.info(this.getClass().getName()+"插入日志开始");
			iAccountLogService.add(accountLog);
			logger.info(this.getClass().getName()+"插入日志结束");
		}
	}
	
	
	@Transactional(transactionManager = "o2oTransactionManager")
	public void ChargingJQtest() {
		
		
		AccountLog accountLog = new AccountLog();
		accountLog.setStartTime(new Date());
		accountLog.setId(UuidUtil.generateShortUuid());
		
		accountLog.setStatus("333");
		accountLog.setEndTime(new Date());
		accountLog.setRequestid("444");
		accountLog.setRequestPs("111111");
		accountLog.setResponsePs("2222222");
		
		accountLog.setLogType("ceshi");
		accountLog.setLoanapplyNo("5555");
		accountLog.setMethodname(Thread.currentThread().getStackTrace()[1].getMethodName());
		
		try {
			System.out.println("try");
			accountLog.setClassname("try");
			int a =1;
			a = a/0;
			accountLogDao.insert(accountLog);
		} catch (Exception e) {
			System.out.println("catch");
			accountLog.setClassname("catch");
			accountLogDao.insert(accountLog);
			throw new RuntimeException();
			//return "退保证金（结清）失败";
		}finally{
			System.out.println("finally");
			accountLogDao.insert(accountLog);
		}
	}	
	
	/**
	 * 根据贷款ID查询借款人可用账号
	 * 
	 * @param loanapplyNo
	 * @return
	 */
	public CustomerEntity getCustomerEntity(String loanapplyNo) {
		logger.info("开始查询贷款信息");
		O2oLoanapplyEntity loanapplyEntity = o2oLoanapplyService.findById(loanapplyNo);
		logger.info("查询贷款信息:{}", loanapplyEntity);
		logger.info("访问CustomerService接口开始");
		CustomerEntity customerEntity = customerService.queryCustomerEntityByCustomerId(loanapplyEntity.getLoanId());
		logger.info("访问CustomerService接口结束，结果：{}", customerEntity);
		return customerEntity;
	}
	
	
}
